use std::borrow::BorrowMut;
use std::cell::{RefCell, RefMut};
use std::ops::Deref;
use std::rc::Rc;
use std::thread::Thread;
use crate::class_file::byte_data_reader::ByteDataReader;
use crate::instruction::instruction::Instruction;
use crate::vm_thread::{VMFrame, VMThread};
use crate::vm_val::{VMValEnum, VMValInteger, VMValLong};

pub struct lconst_0 {}

impl Instruction for lconst_0 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValLong {
            val: VMValLong {
                num: 0
            }
        });
    }


    fn to_string(&self) -> String {
        String::from("lconst_0")
    }
}


pub struct lconst_1 {}

impl Instruction for lconst_1 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValLong {
            val: VMValLong {
                num: 1
            }
        });
    }


    fn to_string(&self) -> String {
        String::from("lconst_1")
    }
}


pub struct iconst_m1 {}

impl Instruction for iconst_m1 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: -1
            }
        });
    }

    fn to_string(&self) -> String {
        String::from("iconst_m1")
    }
}


pub struct iconst_0 {}

impl Instruction for iconst_0 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: 0
            }
        });
    }
    fn to_string(&self) -> String {
        String::from("iconst_0")
    }
}


pub struct iconst_1 {}

impl Instruction for iconst_1 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: 1
            }
        });
    }
    fn to_string(&self) -> String {
        String::from("iconst_1")
    }
}

pub struct iconst_2 {}

impl Instruction for iconst_2 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: 2
            }
        });
    }
    fn to_string(&self) -> String {
        String::from("iconst_2")
    }
}

pub struct iconst_3 {}

impl Instruction for iconst_3 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: 3
            }
        });
    }
    fn to_string(&self) -> String {
        String::from("iconst_3")
    }
}

pub struct iconst_4 {}

impl Instruction for iconst_4 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: 4
            }
        });
    }
    fn to_string(&self) -> String {
        String::from("iconst_4")
    }
}

pub struct iconst_5 {}

impl Instruction for iconst_5 {
    fn exec(&mut self, frame: Rc<RefCell<VMFrame>>, thread: &VMThread) {
        frame.borrow().operand_stack.borrow_mut().push(VMValEnum::VMValInteger {
            val: VMValInteger {
                num: 5
            }
        });
    }
    fn to_string(&self) -> String {
        String::from("iconst_5")
    }
}
